﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;

namespace Progresoft.Scheduler.RemoteInterface.Api
{
	/// <summary>
	/// Класс, управляющий проксями к различным объектам шедулера. НЕ thread-safe.
	/// </summary>
	public class Connector
	{
		/// <summary>
		/// Список зарегестрированных серверов. Ключом является имя сервера, значением - урл
		/// </summary>
		Dictionary<string, string> registeredServers = new Dictionary<string, string>();

		/// <summary>
		/// Зарегистрировать систему в шедулере.
		/// </summary>
		/// <param name="serverKey">Ключ системы.</param>
		/// <param name="serverUrl">URL сервера, который обслуживает данную систему.</param>
		public void RegisterServer(string serverKey, string serverUrl)
		{
			if (string.IsNullOrEmpty(serverKey))
				throw new ArgumentNullException("serverKey", "параметр должен быть указан и должен не быть пустой строкой");

			//регистрироуем новый сервер
			registeredServers.Add(serverKey, serverUrl);
		}

		/// <summary>
		/// Получить Dashboard для всех систем
		/// </summary>
		public DashboardData GetDashboard()
		{
			List<ScheduledTaskHealth> scheduled = new List<ScheduledTaskHealth>();
			List<PeriodicTaskHealth> periodic = new List<PeriodicTaskHealth>();
			// опросим все зарегистрированные серверы
			foreach (string serverUrl in registeredServers.Values.Distinct())
			{
				SchedulerServer server = GetServer(serverUrl);
				DashboardData data = server.GetDashboardData(null);
				scheduled.AddRange(data.ScheduledTasks);
				periodic.AddRange(data.PeriodicTasks);
			}
			return new DashboardData(scheduled, periodic);
		}

        /// <summary>
		/// Получить сервер по URL.
		/// </summary>
		public SchedulerServer GetServer(string url)
		{
			return (SchedulerServer)Activator.GetObject(typeof(SchedulerServer), url);
		}

		/// <summary>
		/// Получить урл сервера по ключу системы перебором всех доступных
		/// зарегестрированных серверов до первого совпадения системы.
		/// примечание: если окажется, что на двух разных серверах зарегестрировано
		/// две системы с одинаковым именем, вернется урл первого опрошенного сервера
		/// </summary>
		/// <param name="system"></param>
		/// <returns></returns>
		public string GetServerUrlBySystem(string system)
		{
			string inaccessible = string.Empty;
			foreach (string key in registeredServers.Keys)
			{
				SchedulerServer server = GetServer(registeredServers[key]);
				
				try
				{
					string[] systemList = server.ListClientSystemKeys();
					if (systemList.Contains(system))
						return registeredServers[key];
				}
				catch
				{
					//сервер недоступен. бывает..
					inaccessible += key + ",";
				}			
			}

			//если мы не нашли нужной нам системы
			throw new Exception(
				string.Format("Система {0} не принадлежит ни одному из опрошенных серверов. {1}",
					system, inaccessible == string.Empty ? "Все зарегестрированные сервера доступны."
						: string.Format("Не удалось установить подключение к {0}", inaccessible)));
		}
	}
}
